﻿using System;
using System.Collections.Generic;
using System.Text;

namespace Kyoh.Lib.Text
{
    /// <summary>Unicode (UTF-32) 値と、Unicode グループを変換する機能を提供します。</summary>
    public static class UnicodeGroups
    {
        #region 検索

        /// <summary>Unicode (UTF-32) 値から、Unicode グループを取得します。</summary>
        /// <param name="unicode">Unicode (UTF-32) の1文字を表す <see cref="System.Int32"/> 値。</param>
        /// <returns>Unicode グループを表す <see cref="UnicodeGroup"/>。</returns>
        public static UnicodeGroup GetGroup(int unicode)
        {
            if (0 <= unicode && (unicode >> 4) < array.Length)
                return array[unicode >> 4];
            else
                return UnicodeGroup.None;
        }

        /// <summary><see cref="System.String"/> から、Unicode グループの列挙を取得します。</summary>
        /// <param name="str">検索対象の <see cref="System.String"/>。</param>
        /// <returns><see cref="System.String"/> の各文字の Unicode 値から、Unicode グループを求めた結果の<see cref="IEnumerable{T}"/>。</returns>
        public static IEnumerable<UnicodeGroup> GetGroups(string str)
        {
            var utf32 = Encoding.UTF32.GetBytes(str);
            for (int i = 0; i < utf32.Length; i += 4)
                yield return UnicodeGroups.GetGroup(BitConverter.ToInt32(utf32, i));
        }
        
        #endregion

        #region グループ配列

        private static readonly UnicodeGroup[] array;

        static UnicodeGroups()
        {
            UnicodeGroup g = UnicodeGroup.None;
            int i = 0;
            array = new UnicodeGroup[0x11000];
            foreach (var map in EnumGroups())
            {
                g++;
                for (; i <= map; i++)
                    array[i] = g;
            }
        }

        private static IEnumerable<int> EnumGroups()
        {
            yield return 0x007;
            yield return 0x00F;
            yield return 0x017;
            yield return 0x024;
            yield return 0x02A;
            yield return 0x02F;
            yield return 0x036;
            yield return 0x03F;
            yield return 0x04F;
            yield return 0x052;
            yield return 0x058;
            yield return 0x05F;
            yield return 0x06F;
            yield return 0x074;
            yield return 0x077;
            yield return 0x07B;
            yield return 0x07F;
            yield return 0x083;
            yield return 0x085;
            yield return 0x08F;
            yield return 0x097;
            yield return 0x09F;
            yield return 0x0A7;
            yield return 0x0AF;
            yield return 0x0B7;
            yield return 0x0BF;
            yield return 0x0C7;
            yield return 0x0CF;
            yield return 0x0D7;
            yield return 0x0DF;
            yield return 0x0E7;
            yield return 0x0EF;
            yield return 0x0FF;
            yield return 0x109;
            yield return 0x10F;
            yield return 0x11F;
            yield return 0x137;
            yield return 0x139;
            yield return 0x13F;
            yield return 0x167;
            yield return 0x169;
            yield return 0x16F;
            yield return 0x171;
            yield return 0x173;
            yield return 0x175;
            yield return 0x177;
            yield return 0x17F;
            yield return 0x18A;
            yield return 0x18F;
            yield return 0x194;
            yield return 0x197;
            yield return 0x19D;
            yield return 0x19F;
            yield return 0x1A1;
            yield return 0x1AA;
            yield return 0x1B7;
            yield return 0x1BB;
            yield return 0x1BF;
            yield return 0x1C4;
            yield return 0x1C7;
            yield return 0x1CC;
            yield return 0x1CF;
            yield return 0x1D7;
            yield return 0x1DB;
            yield return 0x1DF;
            yield return 0x1EF;
            yield return 0x1FF;
            yield return 0x206;
            yield return 0x209;
            yield return 0x20C;
            yield return 0x20F;
            yield return 0x214;
            yield return 0x218;
            yield return 0x21F;
            yield return 0x22F;
            yield return 0x23F;
            yield return 0x243;
            yield return 0x245;
            yield return 0x24F;
            yield return 0x257;
            yield return 0x259;
            yield return 0x25F;
            yield return 0x26F;
            yield return 0x27B;
            yield return 0x27E;
            yield return 0x27F;
            yield return 0x28F;
            yield return 0x297;
            yield return 0x29F;
            yield return 0x2AF;
            yield return 0x2BF;
            yield return 0x2C5;
            yield return 0x2C7;
            yield return 0x2CF;
            yield return 0x2D2;
            yield return 0x2D7;
            yield return 0x2DD;
            yield return 0x2DF;
            yield return 0x2E7;
            yield return 0x2EF;
            yield return 0x2FD;
            yield return 0x2FF;
            yield return 0x303;
            yield return 0x309;
            yield return 0x30F;
            yield return 0x312;
            yield return 0x318;
            yield return 0x319;
            yield return 0x31B;
            yield return 0x31E;
            yield return 0x31F;
            yield return 0x32F;
            yield return 0x33F;
            yield return 0x4DB;
            yield return 0x4DF;
            yield return 0x9FF;
            yield return 0xA48;
            yield return 0xA4C;
            yield return 0xA4F;
            yield return 0xA63;
            yield return 0xA69;
            yield return 0xA6F;
            yield return 0xA71;
            yield return 0xA7F;
            yield return 0xA82;
            yield return 0xA83;
            yield return 0xA87;
            yield return 0xA8D;
            yield return 0xA8F;
            yield return 0xA92;
            yield return 0xA95;
            yield return 0xA97;
            yield return 0xA9D;
            yield return 0xAA5;
            yield return 0xAA7;
            yield return 0xAAD;
            yield return 0xAAF;
            yield return 0xAB2;
            yield return 0xABF;
            yield return 0xD7A;
            yield return 0xD7F;
            yield return 0xDB7;
            yield return 0xDBF;
            yield return 0xDFF;
            yield return 0xF8F;
            yield return 0xFAF;
            yield return 0xFB4;
            yield return 0xFDF;
            yield return 0xFE0;
            yield return 0xFE1;
            yield return 0xFE2;
            yield return 0xFE4;
            yield return 0xFE6;
            yield return 0xFEF;
            yield return 0xFFE;
            yield return 0xFFF;
            yield return 0x1007;
            yield return 0x100F;
            yield return 0x1013;
            yield return 0x1018;
            yield return 0x101C;
            yield return 0x101F;
            yield return 0x1029;
            yield return 0x102D;
            yield return 0x1032;
            yield return 0x1034;
            yield return 0x1039;
            yield return 0x103D;
            yield return 0x1044;
            yield return 0x1047;
            yield return 0x104A;
            yield return 0x1083;
            yield return 0x1085;
            yield return 0x1091;
            yield return 0x1093;
            yield return 0x1099;
            yield return 0x109F;
            yield return 0x10A5;
            yield return 0x10A7;
            yield return 0x10B3;
            yield return 0x10B5;
            yield return 0x10B7;
            yield return 0x10C4;
            yield return 0x10E7;
            yield return 0x1107;
            yield return 0x110C;
            yield return 0x110F;
            yield return 0x1114;
            yield return 0x111D;
            yield return 0x116C;
            yield return 0x123F;
            yield return 0x1247;
            yield return 0x1342;
            yield return 0x16A3;
            yield return 0x16F9;
            yield return 0x1B0F;
            yield return 0x1D0F;
            yield return 0x1D1F;
            yield return 0x1D24;
            yield return 0x1D35;
            yield return 0x1D37;
            yield return 0x1D7F;
            yield return 0x1EEF;
            yield return 0x1F02;
            yield return 0x1F09;
            yield return 0x1F0F;
            yield return 0x1F1F;
            yield return 0x1F2F;
            yield return 0x1F5F;
            yield return 0x1F64;
            yield return 0x1F6F;
            yield return 0x1F77;
            yield return 0x2A6D;
            yield return 0x2B73;
            yield return 0x2B81;
            yield return 0x2FA1;
            yield return 0xE007;
            yield return 0xE01E;
            yield return 0xFFFF;
            yield return 0x10FFF;
        }

        #endregion
    }
}
